﻿namespace TestTool.GUI.Utils
{
    using System;
    using System.Runtime.CompilerServices;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Threading;
    using TestTool.HttpTransport.Interfaces;
    using TestTool.Proxies.Onvif;

    internal class PTZServiceProvider : BaseServiceProvider<PTZClient, PTZ>
    {
        public event PTZConfigurationReceived OnPTZConfigurationsReceived;

        public PTZServiceProvider(string serviceAddress, int messageTimeout) : base(serviceAddress, messageTimeout)
        {
            base.EnableLogResponse = true;
        }

        public void AbosuteRelativeIncrementalMove(bool absolute, string profile, decimal xmin, decimal xmax, decimal ymin, decimal ymax, decimal zmin, decimal zmax)
        {
            base.RunInBackground(delegate {
                PTZVector position = new PTZVector {
                    PanTilt = new Vector2D()
                };
                position.PanTilt.space = absolute ? "http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" : "http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace";
                position.Zoom = new Vector1D();
                position.Zoom.space = absolute ? "http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" : "http://www.onvif.org/ver10/tptz/ZoomSpaces/TranslationGenericSpace";
                for (decimal m = xmin; m <= xmax; m += 0.2M)
                {
                    for (decimal i = ymin; i <= ymax; i += 0.2M)
                    {
                        for (decimal j = zmin; j <= zmax; j += 0.2M)
                        {
                            position.PanTilt.x = (float) m;
                            position.PanTilt.y = (float) i;
                            position.Zoom.x = (float) j;
                            if (absolute)
                            {
                                this.Client.AbsoluteMove(profile, position, null);
                            }
                            else
                            {
                                this.Client.RelativeMove(profile, position, null);
                            }
                            Thread.Sleep(300);
                        }
                    }
                }
            });
        }

        public void AbsoluteMove(string profile, PTZVector position)
        {
            base.RunInBackground(() => this.Client.AbsoluteMove(profile, position, null));
        }

        public void ContinuousMove(string profile, PTZSpeed speed, string timeout)
        {
            base.RunInBackground(() => this.Client.ContinuousMove(profile, speed, timeout));
        }

        public override PTZClient CreateClient(Binding binding, EndpointAddress address)
        {
            return new PTZClient(binding, address);
        }

        public void GetConfigurations()
        {
            base.RunInBackground(delegate {
                PTZConfiguration[] configs = base.Client.GetConfigurations();
                if (this.OnPTZConfigurationsReceived != null)
                {
                    this.OnPTZConfigurationsReceived(configs);
                }
            });
        }

        public PTZNode[] GetNodes()
        {
            Action unsecure = null;
            PTZNode[] nodes = null;
            if (base.Security == Security.None)
            {
                if (unsecure == null)
                {
                    unsecure = delegate {
                        nodes = this.Client.GetNodes();
                    };
                }
                base.ConstructSecurityTolerantAction(unsecure)();
            }
            else
            {
                nodes = base.Client.GetNodes();
            }
            return nodes;
        }

        public void RelativeMove(string profile, PTZVector translation)
        {
            base.RunInBackground(() => this.Client.RelativeMove(profile, translation, null));
        }

        public void Stop(string profile, bool panTilt, bool zoom)
        {
            base.RunInBackground(() => this.Client.Stop(profile, panTilt, zoom));
        }

        public delegate void PTZConfigurationReceived(PTZConfiguration[] configs);
    }
}

